﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using TradeClient.Logic.Entity;
using WAF.EntityFramework;

namespace TradeClient.Logic.TradeCore
{
    public class QuoteManager
    {
        /// <summary>
        /// 是否读取实时行情
        /// </summary>
        private static bool isContinue;

        /// <summary>
        /// 单例模式实例对象
        /// </summary>
        private static QuoteManager instance;

        /// <summary>
        /// 行情数据队列
        /// </summary>
        private Queue<QuoteData> queueQuote;

        /// <summary>
        /// 存储所有K线列表的列表
        /// </summary>
        private List<KLineSeries> listQuote;


        /******************************** Public ********************************/

        /// <summary>
        /// 取得行情管理类对象实例
        /// </summary>
        /// <returns>行情对象实例</returns>
        public static QuoteManager GetInstance()
        {
            if (instance == null)
                instance = new QuoteManager();

            return instance;
        }

        /// <summary>
        /// 停止获取实时行情
        /// </summary>
        public void Stop()
        {
            isContinue = false;
        }

        /// <summary>
        /// 增加一个K线序列
        /// </summary>
        /// <param name="series">K线序列</param>
        public void Add(KLineSeries series)
        {
            listQuote.Add(series);
        }

        /// <summary>
        /// 移除一个K线序列
        /// </summary>
        /// <param name="series">K线序列</param>
        public void Remove(KLineSeries series)
        {
            listQuote.Remove(series);
        }

        /// <summary>
        /// 将最新行情放入队列
        /// </summary>
        /// <param name="queueQuoteData">最新行情结构</param>
        public void EnqueueQuote(QuoteData queueQuoteData)
        {
            //锁定队列防止多个线程同时放入数据
            lock (queueQuote)
            {
                queueQuote.Enqueue(queueQuoteData);
            }
        }

        /// <summary>
        /// 开始获取实时行情
        /// </summary>
        public void Start()
        {
            StartCtpQuote();
        }

        /// <summary>
        /// 获取订阅了行情的品种
        /// </summary>
        /// <returns>品种数组</returns>
        public PolicyQuote[] GetSubscribeQuote()
        { 
            PolicyQuote[] quotes = EntityAction.Select<PolicyQuote>("SELECT distinct * FROM PolicyQuote WHERE Market='" + MarketType.Futures.ToString() + "'");

            return quotes;
        }

        /// <summary>
        /// 获取订阅了行情的品种代码
        /// </summary>
        /// <returns>代码数组</returns>
        public string[] GetSubscribeInstruments()
        {
            PolicyQuote[] quotes = GetSubscribeQuote();

            string[] subscribeInstruments = new string[quotes.Length];

            for (int i = 0; i < quotes.Length; i++)
                subscribeInstruments[i] = quotes[i].Code;

            return subscribeInstruments;
        }

      
        /******************************** Private ********************************/

        private void StartCtpQuote()
        {
            CtpAccount ctpAccount = AccountManager.GetCtpAccount();

            //string[] mdFront = { @"tcp://asp-sim2-md1.financial-trading-platform.com:26213" };
            string[] mdFront = { @"tcp://cifco-md1.financial-trading-platform.com:41213" };

            CtpQuote ctpQuote = new CtpQuote(ctpAccount, mdFront, GetSubscribeInstruments());
        }

        /// <summary>
        /// 私有构造函数
        /// </summary>
        private QuoteManager()
        {
            isContinue = true;

            //初始化行情数据队列（默认可缓存100个数据）
            queueQuote = new Queue<QuoteData>(100);

            //初始化K线列表列表（默认可缓存100条K线）
            listQuote = new List<KLineSeries>(100);

            //在新线程中取出队列中的行情数据并在该线程中执行所有策略运算
            Task.Factory.StartNew(this.DequeueQuote);
        }

        /// <summary>
        /// 从队列中获取行情数据
        /// </summary>
        private void DequeueQuote()
        {
            while (isContinue)
            {
                QuoteData queueQuoteData = (queueQuote.Count > 0) ? queueQuote.Dequeue() : null;

                if (queueQuoteData != null)
                    PriceChange(queueQuoteData);
                else
                    System.Threading.Thread.Sleep(200); 
            }
        }

        /// <summary>
        /// 更新各级别K线价格并引发价格变化事件和K线新增事件
        /// </summary>
        /// <param name="instrumentID">合约代码</param>
        /// <param name="price">最新价格</param>
        /// <param name="updateTime">更新时间</param>
        private void PriceChange(QuoteData queueQuoteData)
        {
            foreach (KLineSeries series in listQuote)
            {
                //从字典中取出对应的K线序列
                if (series.Market == queueQuoteData.Market && series.Code == queueQuoteData.Code)
                {
                    //更新K线价格并引发事件
                    series.UpdatePrice(queueQuoteData);
                }
            }
        }
    }
}
